package kmlisten

import (
	"fmt"
	hook "github.com/robotn/gohook"
	"time"
)

const LongPressDuration = 550 // 长按时间阈值
type MouseLongClickHandler func(code uint16)
type KbClickHandler func(codes []uint16)

const KeyTypeMouse = "mouse"
const KeyTypeKb = "keyboard"

type KeyInfo struct {
	Code    uint16 //键值
	AddTime time.Time
	KeyType string
}

type KMListener struct {
	ListenEvent         chan hook.Event
	mouseLongClickEvent MouseLongClickHandler
	kbClickEvent        KbClickHandler
	CurrKyeBoardCodes   []*KeyInfo
	CurrMouseCodes      []*KeyInfo
}

func NewListener(mouseLongClickEvent_ MouseLongClickHandler, kbClickEvent_ KbClickHandler) *KMListener {
	listen := &KMListener{
		mouseLongClickEvent: mouseLongClickEvent_,
		kbClickEvent:        kbClickEvent_,
	}
	go listen.listenEntry()
	return listen
}

func (s *KMListener) listenEntry() {
	s.ListenEvent = hook.Start()
	defer hook.End()

	for true {
		///3 4 5 键盘按键：按下不动触发3-松开瞬间触发4和5（先4后5）
		//7 8 6 鼠标按键 Button
		//9 鼠标移动
		select {
		case i := <-s.ListenEvent:
			switch i.Kind {
			case hook.HookEnabled:
				//fmt.Printf("【%v】HookEnabled -%v\n", i.Kind, i)
				break
			case hook.HookDisabled:
				//fmt.Printf("【%v】HookDisabled-%v\n", i.Kind, i)
				break
			case hook.KeyDown:
				//fmt.Printf("【%v】KeyDown-%v\n", i.Kind, i)
				break
			case hook.KeyHold: //4-按键按下
				s.KbAdd(i.Rawcode)
				//fmt.Printf("【%v】KeyHold-%v\n", i.Kind, i)
				break
			case hook.KeyUp: //5-按键松开
				s.KbDel(i.Rawcode)
				//fmt.Printf("【%v】KeyUp-%v\n", i.Kind, i)
				break

			case hook.MouseUp: //6鼠标按键松开1
				s.MouseKeyDel(i.Button)
				//fmt.Printf("【%v】MouseUp-%v\n", i.Kind, i)
				break
			case hook.MouseHold: //7鼠标按键按下
				s.MouseKeyAdd(i.Button)
				//fmt.Printf("【%v】MouseHold-%v\n", i.Kind, i)
				break
			case hook.MouseDown: //8鼠标按键松开1--不用
				//fmt.Printf("【%v】MouseDown-%v\n", i.Kind, i)
				break
			case hook.MouseMove: //9 鼠标移动
				//fmt.Printf("【%v】MouseMove-%v\n", i.Kind, i)
				break
			case hook.MouseDrag:
				//fmt.Printf("【%v】MouseDrag-%v\n", i.Kind, i)
				break
			case hook.MouseWheel: //滚轮移动
				//fmt.Printf("【%v】MouseWheel-%v\n", i.Kind, i)
				break
			case hook.FakeEvent:
				//fmt.Printf("【%v】FakeEvent-%v\n", i.Kind, i)
				break
			default:
				//fmt.Printf("【%v】other-%v\n", i.Kind, i)
				break
			}
		}
	}
}

func (s *KMListener) MouseKeyAdd(code uint16) {
	s.CurrMouseCodes = InsertCode(s.CurrMouseCodes, code, KeyTypeMouse)
	s.CheckLongClick(code)
}

func (s *KMListener) MouseKeyDel(code uint16) {
	newList := DeleteCode(s.CurrMouseCodes, code)
	s.CurrMouseCodes = newList

}

// CheckLongClick 监控该按键是否还按着，如果时间达到则属于长按是否属于长按
func (s *KMListener) CheckLongClick(code uint16) {
	if s.mouseLongClickEvent == nil {
		return
	}

	waitTime := 0

	go func() {
		for true {
			isExists := CodeExists(s.CurrMouseCodes, code)
			if isExists {
				if waitTime > LongPressDuration {
					//事件达到，属于长按，调用通知
					s.mouseLongClickEvent(code)
					break
				} else {
					time.Sleep(time.Millisecond + 30)
					waitTime += 30
				}
			} else {
				//该按键已经松开了，不属于长按
				break
			}
		}
	}()
}

func (s *KMListener) KbAdd(code uint16) {
	s.CurrKyeBoardCodes = InsertCode(s.CurrKyeBoardCodes, code, KeyTypeMouse)
	s.NotifyKbEventK()
}

func (s *KMListener) KbDel(code uint16) {
	s.CurrKyeBoardCodes = DeleteCode(s.CurrKyeBoardCodes, code)

	//s.NotifyKbEventK()
}

func (s *KMListener) NotifyKbEventK() {
	if len(s.CurrKyeBoardCodes) > 1 && s.kbClickEvent != nil {
		list := make([]uint16, 0)
		for _, codeInfo := range s.CurrKyeBoardCodes {
			list = append(list, codeInfo.Code)
		}
		s.kbClickEvent(list)
	}
}

func CodeExists(MouseCodes []*KeyInfo, code uint16) bool {
	fmt.Printf("%v-%+v", code, MouseCodes)
	for _, mouseCodeInfo := range MouseCodes {
		if mouseCodeInfo.Code == code {
			return true
		}
	}

	return false
}
func InsertCode(MouseCodes []*KeyInfo, code uint16, KeyType string) []*KeyInfo {
	// 检查是否已存在相同的键值
	for _, key := range MouseCodes {
		if key.Code == code {
			return MouseCodes // 如果存在相同的键值，直接返回切片
		}
	}

	// 创建新的 KeyInfo 对象
	newKey := &KeyInfo{
		Code:    code,
		AddTime: time.Now(),
		KeyType: KeyType,
	}

	// 将新的 KeyInfo 对象插入到切片中
	MouseCodes = append(MouseCodes, newKey)
	return MouseCodes
}

func DeleteCode(MouseCodes []*KeyInfo, code uint16) []*KeyInfo {

	// 遍历切片找到匹配的键值并删除
	for i, key := range MouseCodes {
		if key.Code == code {

			// 从切片中删除指定位置的元素
			MouseCodes = append(MouseCodes[:i], MouseCodes[i+1:]...)
			break
		}
	}

	return MouseCodes
}
